package org.ehe.erp.service.product.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.ehe.common.core.exception.BusinessException;
import org.ehe.common.core.utils.MapstructUtils;
import org.ehe.common.core.utils.StringUtils;
import org.ehe.erp.domain.product.CodingRule;
import org.ehe.erp.domain.product.ErpProductCategory;
import org.ehe.erp.domain.product.bo.CodingRuleBo;
import org.ehe.erp.domain.product.vo.CodingRuleVo;
import org.ehe.erp.mapper.product.CodingRuleMapper;
import org.ehe.erp.mapper.product.ErpProductCategoryMapper;
import org.ehe.erp.service.product.ICodingRuleService;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.IntStream;
/**
 * @author :zhangnn
 * @className :CodingRuleServiceImpl
 * @description: TODO
 * @date 2025-09-06 14:57:10
 */
@RequiredArgsConstructor
@Service
public class CodingRuleServiceImpl extends ServiceImpl<CodingRuleMapper, CodingRule> implements ICodingRuleService {

    private final CodingRuleMapper baseMapper;
    private final ErpProductCategoryMapper categoryMapper;

    @Override
    public CodingRuleVo queryById(Long id) {
        CodingRuleVo vo = baseMapper.selectVoById(id);
        if (vo != null && vo.getCategoryId() != null) {
            ErpProductCategory category = categoryMapper.selectById(vo.getCategoryId());
            if (category != null) {
                vo.setCategoryName(category.getName());
            }
        }

        // 设置状态名称
        if (vo != null) {
            vo.setStatusName(vo.getStatus() == 1 ? "启用" : "禁用");
        }

        return vo;
    }

    @Override
    public List<CodingRuleVo> queryList(CodingRuleBo bo) {
        LambdaQueryWrapper<CodingRule> lqw = buildQueryWrapper(bo);
        List<CodingRuleVo> list = baseMapper.selectVoList(lqw);

        // 填充分类名称和状态名称
        for (CodingRuleVo vo : list) {
            if (vo.getCategoryId() != null) {
                ErpProductCategory category = categoryMapper.selectById(vo.getCategoryId());
                if (category != null) {
                    vo.setCategoryName(category.getName());
                }
            } else {
                vo.setCategoryName("全局规则");
            }
            vo.setStatusName(vo.getStatus() == 1 ? "启用" : "禁用");
        }

        return list;
    }

    private LambdaQueryWrapper<CodingRule> buildQueryWrapper(CodingRuleBo bo) {
        LambdaQueryWrapper<CodingRule> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getCategoryId() != null, CodingRule::getCategoryId, bo.getCategoryId());
        lqw.eq(bo.getLevel() != null, CodingRule::getLevel, bo.getLevel());
        lqw.like(StringUtils.isNotBlank(bo.getRuleName()), CodingRule::getRuleName, bo.getRuleName());
        lqw.eq(bo.getStatus() != null, CodingRule::getStatus, bo.getStatus());
        lqw.orderByAsc(CodingRule::getLevel);
        lqw.orderByDesc(CodingRule::getId);
        return lqw;
    }

    @Override
    public Boolean insertByBo(CodingRuleBo bo) {
        // 验证唯一性
        if (!checkRuleUnique(bo)) {
            throw new BusinessException("该层级的编码规则已存在");
        }

        CodingRule add = MapstructUtils.convert(bo, CodingRule.class);

        // 设置默认值
        if (add.getIncrementStep() == null) {
            add.setIncrementStep(1);
        }
        if (StringUtils.isBlank(add.getSeparatorCode())) {
            add.setSeparatorCode(".");
        }

        return baseMapper.insert(add) > 0;
    }

    @Override
    public Boolean updateByBo(CodingRuleBo bo) {
        // 验证唯一性（排除自己）
        if (!checkRuleUnique(bo)) {
            throw new BusinessException("该层级的编码规则已存在");
        }

        CodingRule update = MapstructUtils.convert(bo, CodingRule.class);
        return baseMapper.updateById(update) > 0;
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            // 检查是否有分类正在使用这些规则
            for (Long id : ids) {
                CodingRule rule = baseMapper.selectById(id);
                if (rule != null && rule.getStatus() == 1) {
                    // 检查是否有分类使用了这个层级
                    boolean hasCategories = categoryMapper.exists(
                        new LambdaQueryWrapper<ErpProductCategory>()
                            .eq(ErpProductCategory::getLevel, rule.getLevel())
                            .eq(ErpProductCategory::getDelFlag, 0)
                    );
                    if (hasCategories) {
                        throw new BusinessException(String.format("编码规则[%s]正被分类使用，无法删除", rule.getRuleName()));
                    }
                }
            }
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public Boolean checkRuleUnique(CodingRuleBo bo) {
        LambdaQueryWrapper<CodingRule> lqw = new LambdaQueryWrapper<>();
        lqw.eq(CodingRule::getLevel, bo.getLevel());

        if (bo.getCategoryId() != null) {
            lqw.eq(CodingRule::getCategoryId, bo.getCategoryId());
        }

        if (bo.getId() != null) {
            lqw.ne(CodingRule::getId, bo.getId());
        }

        return !baseMapper.exists(lqw);
    }

    @Override
    public List<Integer> getLevelOptions() {
        return IntStream.rangeClosed(1, 10).boxed().toList();
    }

    @Override
    public String previewCode(CodingRuleBo bo) {
        if (bo.getDigitLength() == null || bo.getStartNumber() == null) {
            return "请设置数字位数和起始数字";
        }

        String prefix = bo.getPrefix() == null ? "" : bo.getPrefix();
        String format = "%0" + bo.getDigitLength() + "d";
        String numberPart = String.format(format, bo.getStartNumber());

        String currentCode = prefix + numberPart;

        // 如果有分隔符，展示完整编码示例
        if (StringUtils.isNotBlank(bo.getSeparatorCode()) && bo.getLevel() > 1) {
            String parentExample = bo.getLevel() == 2 ? "00" :
                bo.getLevel() == 3 ? "00.001" :
                    "00.001.01001";
            return parentExample + bo.getSeparatorCode() + currentCode;
        }

        return currentCode;
    }
}
